﻿using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Web;
using Microsoft.Commerce.Common;
using Microsoft.Commerce.Common.MessageBuilders;
using Microsoft.Commerce.Contracts.Messages;
using System.Collections.Generic;

namespace MusicWorks.Service.Helpers
{
    /// <summary>
    /// The purpose of the BrokerHelper is to encapsulate the grouping of calls into one call to the broker.
    /// </summary>
    public class BrokerHelper : MusicWorks.Service.Helpers.IRequestBroker
    {
        private const string DefaultChannelName = @"MusicWorks";
        private const string SiteContextKey = "siteContext";
        private static readonly object locker = new object();
        private static readonly object padlock = new object();
        private static BrokerHelper current;
        private static OperationServiceAgent operationService;
        private readonly CommerceRequestContext _requestContext;
        private CommerceMultiOperation _multiOperation;
        private int _operationCount;
        private CommerceResponse _response;

        /// <summary>
        /// Initializes a new instance of the BrokerHelper class.
        /// </summary>
        private BrokerHelper()
        {
            _requestContext = GetCurrentRequestContext();
            _multiOperation = new CommerceMultiOperation();
            _operationCount = 0;
            _response = null;
        }

        /// <summary>
        /// Gets the operation count.
        /// </summary>
        /// <value>The operation count.</value>
        public int OperationCount
        {
            get { return _operationCount; }
        }

        /// <summary>
        /// Gets the request context.
        /// </summary>
        /// <value>The request context.</value>
        public CommerceRequestContext CommerceRequestContext
        {
            get { return _requestContext; }
        }


        //TODO: For R2 release remove the depencdency on the HTTP Cache
        public static BrokerHelper Current
        {
            get
            {
                lock (padlock)
                {
                    if (HttpContext.Current.Items[SiteContextKey] != null)
                    {
                        return (BrokerHelper)HttpContext.Current.Items[SiteContextKey];
                    }

                    current = new BrokerHelper();
                    HttpContext.Current.Items[SiteContextKey] = current;
                    return current;
                }
            }
        }


        /// <summary>
        /// Gets OperationService instance
        /// </summary>
        private static OperationServiceAgent OperationService
        {
            get
            {
                if (operationService == null)
                {
                    lock (locker)
                    {
                        if (operationService == null)
                        {
                            operationService = new OperationServiceAgent();
                        }
                    }
                }

                return operationService;
            }
        }

        /// <summary>
        /// Processes the request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>The response of the request.</returns>
        public CommerceResponse ProcessRequest(CommerceRequest request)
        {
            return OperationService.ProcessRequest(Current.GetCurrentRequestContext(), request);
        }


        /// <summary>
        /// Executes this instance.
        /// </summary>
        public void Execute()
        {
            if (OperationCount > 0)
            {
                _response = ProcessRequest(_multiOperation.ToRequest());

                // reset;
                _operationCount = 0;
                _multiOperation = new CommerceMultiOperation();
            }
        }

        /// <summary>
        /// Adds the request.
        /// </summary>
        /// <typeparam name="TItem">The type of the item.</typeparam>
        /// <param name="builder">The builder.</param>
        public void AddRequest(CommerceBaseBuilder builder)
        {
            _operationCount++;
            _multiOperation.Add(builder);
        }

        public CommerceRequestContext GetCurrentRequestContext()
        {
            var sessionContext = new CommerceRequestContext();
            sessionContext.UserId = HttpContext.Current.User.Identity.Name;
            sessionContext.Channel = DefaultChannelName;
            sessionContext.UserLocale = Thread.CurrentThread.CurrentCulture.Name;
            sessionContext.UserUILocale = Thread.CurrentThread.CurrentUICulture.Name;
            sessionContext.RequestId = Guid.NewGuid().ToString("B");
            return sessionContext;
        }

        /// <summary>
        /// Gets the responses.
        /// </summary>
        /// <value>The responses.</value>
        public IEnumerable<CommerceOperationResponse> Responses
        {
            get
            {
                var operationResponses = new Collection<CommerceOperationResponse>();
                if (_response != null)
                {
                    foreach (CommerceOperationResponse operationResponse in _response.OperationResponses)
                    {
                        operationResponses.Add(operationResponse);
                    }
                }

                return operationResponses;
            }
        }
    }
}